iT邦幫忙

2024 iThome 鐵人賽

DAY 11
0
自我挑戰組

30 天 vueuse 原始碼閱讀與實作系列 第 11

[Day 11] useMouse - 基本功能

  • 分享至 

  • xImage
  •  

官方 Demo:https://vueuse.org/core/useMouse/

先拔掉幾個參數,實作一個簡易版本,之後再把其餘參數 & 功能新增進來。

基本功能

// src/compositions/useMouse.js

import { ref } from 'vue'
import { useEventListener } from '@/compositions/useEventListener'
import { defaultWindow } from '@/helper'

const UseMouseBuiltinExtractors = {
  page: event => [event.pageX, event.pageY],
  client: event => [event.clientX, event.clientY],
  screen: event => [event.screenX, event.screenY],
}

export function useMouse(options = {}) {
  const {
    type = 'page',
    initialValue = { x: 0, y: 0 },
    window = defaultWindow,
    target = window,
  } = options

  const x = ref(initialValue.x)
  const y = ref(initialValue.y)
	
  const extractor = typeof type === 'function'
    ? type
    : UseMouseBuiltinExtractors[type]

  const mouseHandler = (event) => {
    const result = extractor(event)

    if (result) {
      [x.value, y.value] = result
    }
  }

  const mouseHandlerWrapper = event => mouseHandler(event)

  if (target) {
    const listenerOptions = { passive: true }
    useEventListener(target, ['mousemove', 'dragover'], mouseHandlerWrapper, listenerOptions)
  }

  return {
    x,
    y,
  }
}

可以看到整個 useMouse 流程的開始是在之前實作的 useEventListener,這邊是在 target 身上加 mousemove, dragover 的事件監聽,觸發事件的時候執行 mouseHandlerWrapper ,並傳入 listenerOptions

listenerOptions{ passive: true } 的設定,來告訴瀏覽器,事件監聽器永遠不會呼叫 preventDefault(),來提高效能。

mouseHandlerWrapper listener 被觸發的時候會呼叫 event => mouseHandler(event)

mouseHandler 就是最後更新 x、y 值的地方,接著來看看這次的重點: extractor(event)

// src/compositions/useMouse.js

// ...略

const UseMouseBuiltinExtractors = {
  page: event => [event.pageX, event.pageY],
  client: event => [event.clientX, event.clientY],
  screen: event => [event.screenX, event.screenY],
}

const extractor = typeof type === 'function'
    ? type
    : UseMouseBuiltinExtractors[type]

// ...略

我們現在 type 的預設值是 page,extractor('page') 會拿到 event => [event.pageX, event.pageY],所以我們最後回傳出去的 x、y 值就是 event.pageXevent.pageY

看到官網 Demo 的 Custom Extractor 區塊,type 可以傳入 function event => [event.offsetX, event.offsetY],以官網 Demo 的用法來說,target 傳入的是 Demo 區塊底下那塊灰色的 element,[event.offsetX, event.offsetY] 坐標是相對於觸發事件的目標元素(灰色 element)的左上角 (0, 0) 計算的,所以最終的結果就會像官網 Demo 那樣。


今天就先寫到這邊,明天開始會把 useMouse 的其他參數加進來一起看~


上一篇
[Day 10] useEventListener - unit test
下一篇
[Day 12] useMouse - 加入其他參數 & 功能
系列文
30 天 vueuse 原始碼閱讀與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言